package com.batis.source.parsing;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;

/**
 * 解析xml文件信息 有xml的原始documen数据
 * @author isam2016
 * @create 2021-08-26 11:33 AM
 */
public class MYXPathParser {
    private final Document document;
    private boolean validation;
    private EntityResolver entityResolver;
    private Properties variables;
    private XPath xpath;


    public MYXPathParser(Reader reader, boolean validation, Properties variables) {
        commonConstructor(validation, variables, entityResolver);
        this.document = createDocument(new InputSource(reader));
    }

    public Document createDocument(InputSource inputSource){
        try {
            // 解析并获取Document对象:
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(inputSource);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Error("xml parse Error");
        }
    }
    // expression 路径表达式
    public MYXnode evalNode(String expression) {
        return evalNode(document, expression);
    }

    public MYXnode evalNode(Object root, String expression) {
        // 获取/configuration 节点数据
        Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
        if (node == null) {
            return null;
        }
        return new MYXnode(this, node, variables);
    }

    /**
     *
     * @param expression 路径表达式
     * @param root   document
     * @param returnType 节点类型
     * @return
     */
    private Object evaluate(String expression, Object root, QName returnType) {
        try {
            // 选取节点
            return xpath.evaluate(expression, root, returnType);
        } catch (Exception e) {
            throw new Error("Error evaluating XPath.  Cause: " + e, e);
        }
    }
    private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
        this.validation = validation;
        this.entityResolver = entityResolver;
        this.variables = variables;
        XPathFactory factory = XPathFactory.newInstance();
        this.xpath = factory.newXPath();
    }

}
